/*
 * Copyright 2011 www.pretty-tools.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */



#include "stdafx.h"
#include "ScriptBuilder.h"
#include <assert.h>

struct DtdPair {
    CString strEntity;
    CString strValue;
};

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// The one and only application object

CWinApp theApp;

using namespace std;

int SortByLength(const void *arg1, const void *arg2)
{
   return ((DtdPair*)arg2)->strEntity.GetLength() - ((DtdPair*)arg1)->strEntity.GetLength();
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	// initialize MFC and print and error on failure
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		// TODO: change error code to suit your needs
		_tprintf(_T("Fatal Error: MFC initialization failed\n"));
		return 1;
	}

    if (argc < 3)
        return -1;

    CArray<DtdPair> dtd;
    if (argc >= 4)
    {
        CStdioFile fin(argv[3], CFile::modeRead);
        CString strPattern = "<!ENTITY ";
        for (CString str; fin.ReadString(str); )
        {
            int idx = str.Find(strPattern);
            if (idx == -1) continue;

            int idx2 = str.Find('\"', idx + strPattern.GetLength());
            int idx3 = str.ReverseFind('\"');
            assert(idx2 != -1 && idx3 != -1);

            DtdPair pair;
            pair.strEntity = str.Mid(idx+strPattern.GetLength(), idx2-idx - strPattern.GetLength());
            pair.strEntity.Trim();
            
            pair.strValue = str.Mid(idx2+1, idx3-idx2 - 1);
            pair.strValue.Trim();

            dtd.Add(pair);
        }
        // sort by length
        if (dtd.GetCount()) qsort(dtd.GetData(), dtd.GetCount(), sizeof(DtdPair), SortByLength);
    }

    CString strPath = argv[1];
    int lastSlash = strPath.ReverseFind('\\');
    if (lastSlash != -1)
        strPath = strPath.Mid(0, lastSlash+1);
    else
        strPath.Empty();

    CStdioFile fin(argv[1], CFile::modeRead);
    CStdioFile fout(argv[2], CFile::modeWrite | CFile::modeCreate);

    CString strScriptPattern = "<script src=\"";
    CString strCSSPattern = "<link href=\"";
    for (CString str; fin.ReadString(str); )
    {
        for (int j = 0; j < dtd.GetCount(); ++j)
        {
            str.Replace(dtd[j].strEntity, dtd[j].strValue);
        }

        int idx;
        if ((idx = str.Find(strScriptPattern)) != -1)
        {
            int idx2 = str.Find("\"", idx + strScriptPattern.GetLength());
            assert(idx2 != -1);

            fout.WriteString("<script language=\"jscript\" type=\"text/jscript\">\n");

            CString strJSFile = str.Mid(idx+strScriptPattern.GetLength(), idx2-idx - strScriptPattern.GetLength());
            CStdioFile fjs(strPath+strJSFile, CFile::modeRead);
            for (CString strJS; fjs.ReadString(strJS); )
            {
                fout.WriteString(strJS);
                fout.WriteString("\n");
            }

            fout.WriteString("</script>\n");
            continue;
        }

        if ((idx = str.Find(strCSSPattern)) != -1 && str.Find("text/css") != -1)
        {
            int idx2 = str.Find("\"", idx + strScriptPattern.GetLength());
            assert(idx2 != -1);

            fout.WriteString("<style type=\"text/css\">\n");

            CString strCSSFile = str.Mid(idx+strCSSPattern.GetLength(), idx2-idx - strCSSPattern.GetLength());
            CStdioFile fcss(strPath+strCSSFile, CFile::modeRead);
            for (CString strCSS; fcss.ReadString(strCSS); )
            {
                if (!strCSS.IsEmpty())
                    fout.WriteString("\t");
                fout.WriteString(strCSS);
                fout.WriteString("\n");
            }

            fout.WriteString("</style>\n");
            continue;
        }

        fout.WriteString(str);
        fout.WriteString("\n");
    }

	return 0;
}
